package org.shock.ss.sms.action.system;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.shock.ss.sms.bean.system.Updatecfg;
import org.shock.ss.sms.commons.annotation.RightAnno;
import org.shock.ss.sms.commons.utils.FileUtils;
import org.shock.ss.sms.commons.utils.ReflexUtils;

public class UpdateAction {
	private final static String SUCCESS = "success";
	private Logger log = Logger.getLogger(this.getClass());
	private String message = "";
	private String action = "";
	private String jmpUrl = "javascript:history.go(-1)";
	private Integer jmptime = 3;
	private Updatecfg cfg = new Updatecfg();
	private String upAll = "";
	private String remoteOrlocal = "";
	private File file;
	private Map<String, String> fileMap = new LinkedHashMap<String, String>();
	private String fileFileName;
	private String forder;
	private String logName = "";
	private String logContent = "";
	private static Properties p = new Properties();

	/**
	 * @return the logName
	 */
	public String getLogName() {
		return logName;
	}

	/**
	 * @param logName
	 *            the logName to set
	 */
	public void setLogName(String logName) {
		this.logName = logName;
	}

	/**
	 * @return the logCotent
	 */
	public String getLogContent() {
		return logContent;
	}

	/**
	 * @param logCotent
	 *            the logCotent to set
	 */
	public void setLogContent(String logContent) {
		this.logContent = logContent;
	}

	public String recover() throws Exception {
		File filePath = new File(ServletActionContext.getServletContext().getRealPath("")).getParentFile();
		String path = new File("updater\\recover.bat").getAbsolutePath();
		String bak = new File(forder).getAbsolutePath();
		String dest = filePath.getAbsolutePath();
		System.out.println(bak + "===:" + dest);
		message = "正在还原！服务将重启！请稍后重新登录...";
		jmptime = 10;
		File envDir = new File(path).getParentFile();
		System.out.println(envDir);
		try {
			Runtime.getRuntime().exec("cmd /c start \"jlrecover\" " + path + " " + bak, null, envDir);
		} catch (Exception e) {
			log.error(e, e);
			throw e;
		}
		return SUCCESS;
	}
	public String dbRecover() throws Exception {
		File filePath = new File(ServletActionContext.getServletContext().getRealPath("")).getParentFile();
		String path = new File("updater\\dbrecover.bat").getAbsolutePath();
		String bak = new File(forder).getAbsolutePath();
		System.out.println(bak );
		message = "正在还原！服务将重启！请稍后重新登录...";
		jmptime = 10;
		File envDir = new File(path).getParentFile();
		System.out.println(envDir);
		try {
			Runtime.getRuntime().exec("cmd /c start \"jldbrecover\" " + path + " " + bak, null, envDir);
		} catch (Exception e) {
			log.error(e, e);
			throw e;
		}
		return SUCCESS;
	}
	public String dbUpdate() throws Exception {
		message = "正在还原！服务将重启！请稍后重新登录...";
		jmptime = 10;
		String path = new File("updater\\dbrun.bat").getAbsolutePath();
		File envDir = new File(path).getParentFile();
		System.out.println(envDir);
		try {
			Runtime.getRuntime().exec("cmd /c start \"jldbupdater\" " + path, null, envDir);
		} catch (Exception e) {
			log.error(e, e);
			throw e;
		}
		return SUCCESS;
	}

	public String execute() throws Exception {
		File filePath = new File(ServletActionContext.getServletContext().getRealPath("")).getParentFile();
		File nFile = new File(filePath.getAbsolutePath() + "\\" + fileFileName);
		if (null != file) {
			FileUtils.copy(file, nFile);
		}
		String path = new File("updater\\run.bat").getAbsolutePath();
		System.out.println("===:" + path);
		message = "正在更新！服务将重启！请稍后重新登录...";
		jmptime = 10;
		try {
			File envDir = new File(path).getParentFile();
			System.out.println(envDir);
			Runtime.getRuntime().exec("cmd /c start \"jlupdater\" " + path + " " + upAll + " " + remoteOrlocal, null,
					envDir);
		} catch (IOException e) {
			log.error(e, e);
			throw e;
		}
		return SUCCESS;
	}

	public String updatelogList() {
		File logPath;
		if ("recover".equals(action)) {
			logPath = new File("updater\\log\\recover\\");
		} else {
			logPath = new File("updater\\log\\");
		}
		File[] files = logPath.listFiles();
		if (null != files) {
			Arrays.sort(files, new Comparator<File>() {
				public int compare(File o1, File o2) {
					return -(int) (o1.lastModified() - o2.lastModified());
				}

			});
			for (int i = 0; i < files.length; i++) {
				if (files[i].isFile()) {
					fileMap.put(files[i].getName(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(
							files[i].lastModified())));
				}
			}
		}
		return SUCCESS;
	}

	public String updatelogView() throws Exception {
		File logPath;
		if ("recover".equals(action)) {
			logPath = new File("updater\\log\\recover\\" + logName);
		} else {
			logPath = new File("updater\\log\\" + logName);
		}
		File logFile = new File(logPath.getAbsolutePath());
		if (!logPath.exists()) {
			return SUCCESS;
		}
		StringBuffer sb = new StringBuffer();
		BufferedReader br = new BufferedReader(new FileReader(logFile));
		String tmp;
		while (null != (tmp = br.readLine())) {
			sb.append("<p>" + tmp + "</p>" + "\n");
		}
		System.out.println(sb);
		logContent = sb.toString();
		return SUCCESS;
	}

	public String viewCfg() throws Exception {
		cfg = p2cfg();
		return SUCCESS;
	}

	@RightAnno(rightValue = "updateCfg", rightNote = "版本更新配置")
	public String updateCfg() throws Exception {
		if ("before".equals(action)) {
			cfg = p2cfg();
			File[] files = new File(cfg.getLocalbakpath()).listFiles();
			if (null != files) {
				Arrays.sort(files, new Comparator<File>() {
					public int compare(File o1, File o2) {
						return -(int) (o1.lastModified() - o2.lastModified());
					}

				});
				for (int i = 0; i < files.length; i++) {
					fileMap.put(files[i].getAbsolutePath(), files[i].getName());
				}
			}
			return "before";
		} else {
			p.setProperty("version", cfg.getVersion());
			p.setProperty("updateDate", cfg.getUpdateDate());
			p.setProperty("hostname", cfg.getHostname());
			p.setProperty("localBakPath", cfg.getLocalbakpath());
			p.setProperty("localPath", cfg.getLocalpath());
			p.setProperty("clientPath", cfg.getClientpath());
			p.setProperty("noUpdateFiles", cfg.getNoupdatefiles());
			p.setProperty("port", cfg.getPort() + "");
			p.setProperty("pwd", cfg.getPwd());
			p.setProperty("uid", cfg.getUsid());
			p.setProperty("remoteFile", cfg.getRemotefile());
			p.setProperty("remotePath", cfg.getRemotepath());
			p.storeToXML(new FileOutputStream(new File(System.getProperty("user.dir") + "\\updater\\ftp.xml")), "更新配置",
					"utf8");
			message = "更新成功！";
			jmpUrl = "updateCfg.do?action=before";
			return SUCCESS;
		}

	}

	public String dbCfg() throws Exception {
		if ("before".equals(action)) {
			cfg = p2cfg();
			File[] files = new File(cfg.getDb_backUpPath()).listFiles();
			if (null != files) {
				Arrays.sort(files, new Comparator<File>() {
					public int compare(File o1, File o2) {
						return -(int) (o1.lastModified() - o2.lastModified());
					}

				});
				for (int i = 0; i < files.length; i++) {
					fileMap.put(files[i].getAbsolutePath(), files[i].getName());
				}
			}
			return "before";
		} else {
			System.out.println(ReflexUtils.rwritertoString(cfg));
			p.setProperty("db_version", cfg.getDb_version());
			p.setProperty("db_backUpPath", cfg.getDb_backUpPath());
			p.setProperty("local_dbhost", cfg.getLocal_dbhost());
			p.setProperty("local_dbpwd", cfg.getLocal_dbpwd());
			p.setProperty("local_dbuser", cfg.getLocal_dbuser());
			p.setProperty("remote_dbhost", cfg.getRemote_dbhost());
			p.setProperty("remote_dbpwd", cfg.getRemote_dbpwd());
			p.setProperty("remote_dbuser", cfg.getRemote_dbuser());
			p.storeToXML(new FileOutputStream(new File(System.getProperty("user.dir") + "\\updater\\ftp.xml")), "更新配置",
					"utf8");
			message = "更新成功！";
			jmpUrl = "dbCfg.do?action=before";
			return SUCCESS;
		}

	}

	/**
	 * @return the cfg
	 */
	private Updatecfg p2cfg() throws Exception {
		p.loadFromXML(new FileInputStream(new File(System.getProperty("user.dir") + "\\updater\\ftp.xml")));
		cfg.setVersion(p.getProperty("version"));
		cfg.setDb_version(p.getProperty("db_version"));
		cfg.setDb_updateDate(p.getProperty("db_updateDate"));
		cfg.setDb_backUpPath(p.getProperty("db_backUpPath"));
		cfg.setUpdateDate(p.getProperty("updateDate"));
		cfg.setLocal_dbhost(p.getProperty("dbhost"));
		cfg.setHostname(p.getProperty("hostname"));
		cfg.setLocal_dbhost(p.getProperty("local_dbhost"));
		cfg.setLocal_dbpwd(p.getProperty("local_dbpwd"));
		cfg.setLocal_dbuser(p.getProperty("local_dbuser"));
		cfg.setRemote_dbhost(p.getProperty("remote_dbhost"));
		cfg.setRemote_dbpwd(p.getProperty("remote_dbpwd"));
		cfg.setRemote_dbuser(p.getProperty("remote_dbuser"));
		cfg.setLocalbakpath(p.getProperty("localBakPath"));
		cfg.setLocalpath(p.getProperty("localPath"));
		cfg.setClientpath(p.getProperty("clientPath"));
		cfg.setNoupdatefiles(p.getProperty("noUpdateFiles"));
		cfg.setPort(Integer.parseInt(p.getProperty("port")));
		cfg.setPwd(p.getProperty("pwd"));
		cfg.setUsid(p.getProperty("uid"));
		cfg.setRemotefile(p.getProperty("remoteFile"));
		cfg.setRemotepath(p.getProperty("remotePath"));
		return cfg;
	}

	public Updatecfg getCfg() {
		return cfg;
	}

	/**
	 * @param cfg
	 *            the cfg to set
	 */
	public void setCfg(Updatecfg cfg) {
		this.cfg = cfg;
	}

	/**
	 * @return the upAll
	 */
	public String getUpAll() {
		return upAll;
	}

	/**
	 * @param upAll
	 *            the upAll to set
	 */
	public void setUpAll(String upAll) {
		this.upAll = upAll;
	}

	/**
	 * @return the remoteOrlocal
	 */
	public String getRemoteOrlocal() {
		return remoteOrlocal;
	}

	/**
	 * @param remoteOrlocal
	 *            the remoteOrlocal to set
	 */
	public void setRemoteOrlocal(String remoteOrlocal) {
		this.remoteOrlocal = remoteOrlocal;
	}

	/**
	 * @return the file
	 */
	public File getFile() {
		return file;
	}

	/**
	 * @param file
	 *            the file to set
	 */
	public void setFile(File file) {
		this.file = file;
	}

	/**
	 * @return the fileFileName
	 */
	public String getFileFileName() {
		return fileFileName;
	}

	/**
	 * @param fileFileName
	 *            the fileFileName to set
	 */
	public void setFileFileName(String fileFileName) {
		this.fileFileName = fileFileName;
	}

	/**
	 * @return the fileMap
	 */
	public Map<String, String> getFileMap() {
		return fileMap;
	}

	/**
	 * @param fileMap
	 *            the fileMap to set
	 */
	public void setFileMap(Map<String, String> fileMap) {
		this.fileMap = fileMap;
	}

	/**
	 * @return the forder
	 */
	public String getForder() {
		return forder;
	}

	/**
	 * @param forder
	 *            the forder to set
	 */
	public void setForder(String forder) {
		this.forder = forder;
	}

	/**
	 * @return the message
	 */
	public String getMessage() {
		return message;
	}

	/**
	 * @param message
	 *            the message to set
	 */
	public void setMessage(String message) {
		this.message = message;
	}

	/**
	 * @return the action
	 */
	public String getAction() {
		return action;
	}

	/**
	 * @param action
	 *            the action to set
	 */
	public void setAction(String action) {
		this.action = action;
	}

	/**
	 * @return the jmpUrl
	 */
	public String getJmpUrl() {
		return jmpUrl;
	}

	/**
	 * @param jmpUrl
	 *            the jmpUrl to set
	 */
	public void setJmpUrl(String jmpUrl) {
		this.jmpUrl = jmpUrl;
	}

	/**
	 * @return the jmptime
	 */
	public Integer getJmptime() {
		return jmptime;
	}

	/**
	 * @param jmptime
	 *            the jmptime to set
	 */
	public void setJmptime(Integer jmptime) {
		this.jmptime = jmptime;
	}
}
